package com.v9.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.v9.common.config.AppConfig;
import com.v9.common.core.service.DefaultUidService;
import com.v9.common.dto.UserDto;
import com.v9.common.exception.BizException;
import com.v9.common.jwt.JwtTokenUtils;
import com.v9.common.security.MD5;
import com.v9.common.utils.IpUtils;
import com.v9.system.domain.*;
import com.v9.system.mapper.UserInfoMapper;
import com.v9.system.mapper.UserRoleMapper;
import com.v9.system.service.*;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户 业务层处理
 *
 * @author shilun
 */
@Service
public class UserInfoServiceImpl extends DefaultUidService<UserInfoMapper, UserInfo> implements UserInfoService {

    @Resource
    private DeptInfoService departmentService;
    @Resource
    private RoleInfoService roleInfoService;
    @Resource
    private MenuInfoService menuInfoService;

    @Resource
    private PositionService positionService;
    @Resource
    private JwtTokenUtils jwtTokenUtils;
    @Resource
    private IpUtils ipUtils;
    @Resource
    private AppConfig appConfig;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Override
    public List<UserInfo> queryUserByDeptId(Long deptId) {
        DeptInfo dept = departmentService.findById(deptId);
        String deptIds = null;
        if (deptId != null) {
            if (dept.getIds() != null) {
                deptIds = dept.getIds() + "|" + dept.getId();
            } else {
                deptIds = String.valueOf(dept.getId());
            }
        }
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper();
        queryWrapper.like(getColumnToField("deptIds"), deptIds);
        return query(queryWrapper);
    }

    @Override
    public List<UserInfo> queryUserByRoleId(Long roleId) {
        return baseMapper.queryByRoleId(roleId);
    }

    @Override
    public UserDto login(String name, String pass) {
        String s = MD5.MD5Str(pass, appConfig.getSecret());
        UserInfo entity = new UserInfo();
        entity.setUsername(name);
        UserInfo user = findByOne(entity);
        if (user == null) {
            throw new BizException("用户或密码错误");
        }
        if (user.getPassword().equals(s)) {
            UserDto userDto = new UserDto();
            userDto.setDeptId(user.getDeptId());
            userDto.setPositionId(user.getPositionId());
            userDto.setIcon(user.getIcon());
            userDto.setRealName(user.getRealName());
            userDto.setUsername(user.getUsername());
            userDto.setNickName(user.getNickName());
            userDto.setGenderType(user.getGenderType());
            userDto.setPhone(user.getPhone());
            userDto.setPermissions(new HashSet<>());
            UserRole userRoleQuery = new UserRole();
            userRoleQuery.setPin(user.getId());
            userDto.setRoles(new HashSet<>());
            userDto.setPin(user.getId());
            userDto.setDeptId(user.getDeptId());
            List<RoleInfo> roleInfos = roleInfoService.queryByPin(user.getPin());
            userDto.setRoles(new HashSet<>());
            userDto.getRoles().addAll(roleInfos.stream().map(RoleInfo::getCode).collect(Collectors.toList()));
            userDto.setPermissions(new HashSet<>());
            List<MenuInfo> menuInfos = menuInfoService.queryByPin(user.getPin());
            List<String> collect = menuInfos.stream().map(MenuInfo::getPerms).collect(Collectors.toList());


            userDto.getPermissions().addAll(collect);
            UserInfo upUser = new UserInfo();
            upUser.setId(user.getId());

            upUser.setLoginDate(new Date());
            upUser.setLoginIp(ipUtils.getIpAddr());
            updateById(upUser);
            DeptInfo deptInfo = departmentService.findById(user.getDeptId());
            if (deptInfo != null) {
                userDto.setDeptName(deptInfo.getName());
            }
            List<DeptInfo> deptInfos = departmentService.querySubDeptListById(user.getDeptId());
            List<String> groups=new ArrayList<>();
            deptInfos.forEach(item->{
                groups.add("d_"+item.getId());
            });
            groups.add("d_"+user.getDeptId());
            Set<String> roles = userDto.getRoles();
            roles.forEach(item->{
                groups.add("r_"+item);
            });
            Position position = positionService.findById(user.getPositionId());
            userDto.setPositionName(position.getName());
            userDto.setIsAdmin(true);
            return userDto;
        }
        throw new BizException("201", "用户或密码错误");
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return null;
    }

    @Override
    public void exit(String token) {
        jwtTokenUtils.delLoginUser(token);
    }


    @Override
    public void bindRole(String pin, List<Long> roleIds) {
        UserRole entity = new UserRole();
        entity.setPin(pin);
        QueryWrapper<UserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pin", pin);
        List<Long> oldRoleIds = userRoleMapper.selectList(queryWrapper).stream().map(userRole -> userRole.getRoleId()).collect(Collectors.toList());

        Collection<Long> delList = CollectionUtils.subtract(Set.copyOf(oldRoleIds), Set.copyOf(roleIds));
        delList.forEach(roleId->{
            QueryWrapper<UserRole> query = new QueryWrapper<>();
            query.eq("pin",pin);
            query.eq("role_id",roleId);
            userRoleMapper.delete(query);
        });
        Collection<Long> addList = CollectionUtils.subtract(Set.copyOf(roleIds), Set.copyOf(oldRoleIds));
        addList.forEach(roleId->{
            UserRole userRole=new UserRole();
            userRole.setRoleId(roleId);
            userRole.setPin(pin);
            userRoleMapper.insert(userRole);
        });
    }

}
